<?php

namespace App\Kuafu\Guanyuan\Command;

use App\Kuafu\Base\Command\Traits\KfGetTimeInterval;
use App\Kuafu\Category\Model\CategoryModel;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Guanyuan\Enum\DishDetailEnum;
use App\Kuafu\Guanyuan\Model\DishDetailCHModel;
use App\Kuafu\Guanyuan\Model\DishDetailModel;
use App\Kuafu\Shop\Model\Shop;
use App\Kuafu\WaiMai\Enum\WaiMaiDBEnum;
use App\Kuafu\WaiMai\Model\WaiMaiOrderDetailModel;
use App\Kuafu\WaiMai\Model\WaiMaiOrderModel;
use App\Library\FeiShu\SendFs;
use App\Library\SnowFlake\SnowFlake;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;

class WaimaiOrderDishDetailCommand extends Command
{
    use KfGetTimeInterval;

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'guanyuan:wmSyncDishDetail 
    {--d=false :  是否直接执行 示例.true - 默认执行前一天数据 false - 交互式执行} 
    {--shopIds= :  手动执行的 shopIds} 
    ';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '观远订单同步:外卖 菜品数据';

    /**
     * @var bool 判断是否写入 ck 数据库
     */
    protected bool $isInCkDb = true;

    /**
     * @var int Ck 报错次数
     */
    protected int $errCkDbNum = 0;

    /**
     * Execute the console command
     */
    public function handle()
    {       // qa 环境关闭运行
        if (isTest()) {
            return false;
        }
        ini_set('memory_limit', '2000M');

        list($startTimeAt, $endTimeAt) = $this->getTimeInterval();

        $this->info('**************** 开始执行脚本 ****************');

        $manualShopIds = $this->option('shopIds');
        if (!$manualShopIds) {
            $inShopList = Shop::getGyShopList()->pluck('name', 'id')->toArray();
        } else {
            // 手动执行
            $inShopList = explode(",", $manualShopIds);
            $inShopList = array_flip($inShopList);
        }

        $systemStartTimeConst = time();

        // 获取所有店铺信息
        $shopList = Shop::query()
                        ->get()
                        ->keyBy('id')
                        ->each(function ($item) {
                            // 处理省市区
                            $ssq = explode('-', $item['addressPrefix']);
                            if (empty($ssq)
                                || empty($ssq[0])
                                || empty($ssq[1])
                                || empty($ssq[2])
                            ) {
                                return;
                            }
                            $item['province'] = $ssq[0];
                            $item['city']     = $ssq[1];
                            $item['district'] = $ssq[2];

                        })
                        ->toArray();

        $queryDate = [];
        $diff      = ($endTimeAt - $startTimeAt) / 86400;

        for ($d = 1; $d <= $diff; $d++) {
            $queryDate[] = [
                'startTime' => $startTimeAt + 86400 * ($d - 2),
                'endTime'   => $startTimeAt + 86400 * $d - 1
            ];
        }
        $systemStartTime = time();

        $loopStartTime = time();
        $loopStepTime  = time();
        foreach ($queryDate as $date) {
            $this->info(date('Y-m-d', $date['startTime']) . '开始导入');
            foreach ($inShopList as $shopId => $shopName) {
                $this->line(vsprintf("%s|耗时%s|%s", [date('Y-m-d H:i:s'), $loopStepTime - $loopStartTime, $shopName]));
                $loopStartTime = time();
                $orderList     = WaiMaiOrderModel::suffix($shopId)
                                                 ->where('createdAt', '>', $date['startTime'])
                                                 ->where('createdAt', '<', $date['endTime'])
                                                 ->where('shopId', $shopId)
                                                 ->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)
                                                 ->get();

                $orderIds      = $orderList->pluck('orderId');
                $orderListById = $orderList->keyBy('orderId')->toArray();

                // 获取所有原订单菜品详情
                $orderDetail = WaiMaiOrderDetailModel::suffix($shopId)->whereIn('orderId', $orderIds)->get()->toArray();

                $insertData = [];
                foreach ($orderDetail as $detail) {
                    $orderInfo = $orderListById[$detail['orderId']];

                    $insert = [
                        'province'       => $shopList[$orderInfo['shopId']]['province'],
                        'city'           => $shopList[$orderInfo['shopId']]['city'],
                        'district'       => $shopList[$orderInfo['shopId']]['district'],
                        'poiName'        => CommonService::zeroFill($shopList[$shopId]['shopCode']) . $shopList[$shopId]['name'],
                        'spuId'          => '',
                        'spuName'        => $detail['productName'],
                        'specs'          => '',
                        'unit'           => $detail['unit'],
                        'firstCateName'  => '',
                        'orderNo'        => $detail['orderId'],
                        'orderId'        => $detail['orderId'],
                        'count'          => $detail['num'],
                        'totalPrice'     => $detail['originalPrice'] / 100,
                        'discountAmount' => ($detail['originalPrice'] - $detail['incomes']) / 100,
//                        'discountAmount' => ($detail['discountPrice']) / 100,
                        'taxExcludedAmt' => $detail['incomes'] / 100,
                        'goodsTime'      => $orderInfo['createdAt'],
                        'orderTime'      => $orderInfo['createdAt'],
                        'checkoutTime'   => $orderInfo['createdAt'],
                        'categoryName'   => $this->switchCategoryName($orderInfo['sourceType']),
                        'sourceName'     => $this->switchCategoryName($orderInfo['sourceType']),
                        'orderPrice'     => $orderInfo['originalPrice'] / 100, //订单原价
                        'orderDiscount'  => $orderInfo['discountPrice'] / 100, //订单优惠
                        'orderIncome'    => $orderInfo['expectIncome'] / 100, // 订单实收
                        'flagName'       => '',
                        'createdAt'      => date('Y-m-d H:i:s'),
                        'updatedAt'      => date('Y-m-d H:i:s'),
                        'discountName'   => '',
                        'source'         => $orderInfo['sourceType'],
                        'dataFrom'       => 'kuafu',
                    ];

                    $discountName = "";
                    if ($detail['discountPrice'] > 0) {
                        $discountName = "外卖-" . $this->getSourceName($orderInfo['sourceType']) . "外卖";
                    }

                    $insert['discountName'] = $discountName;

                    $insertData[] = $insert;
                }


                if (!empty($insertData)) {
                    // 删除库里对应的数据
                    DishDetailModel::query()
                                   ->where('checkoutTime', '>=', date('Y-m-d H:i:s', $date['startTime']))
                                   ->where('checkoutTime', '<=', date('Y-m-d H:i:s', $date['endTime']))
                                   ->where("poiName", "like",
                                       CommonService::zeroFill($shopList[$shopId]['shopCode']) . "%")
                                   ->whereIn('source', [DishDetailEnum::SOURCE_MEITUAN, DishDetailEnum::SOURCE_ELEMO])
                                   ->delete();

                    try {
                        if ($this->isInCkDb) {
                            DishDetailCHModel::query()
                                             ->where('checkoutTime', '>=', date('Y-m-d H:i:s', $date['startTime']))
                                             ->where('checkoutTime', '<=', date('Y-m-d H:i:s', $date['endTime']))
                                             ->where("poiName", 'LIKE',
                                                 CommonService::zeroFill($shopList[$shopId]['shopCode']) . "%")
                                             ->whereIn('source',
                                                 [DishDetailEnum::SOURCE_MEITUAN, DishDetailEnum::SOURCE_ELEMO])
                                             ->delete();
                        }


                    } catch (\Exception $exception) {
                        $this->errCkDbNum++;
                        if ($this->errCkDbNum > 3) {
                            $this->isInCkDb = false;
                            self::sendFs('外卖 ck 的数据异常,已经停止入 ck 数据库', ['3fgc8798']);
                        }
                    }

                    collect($insertData)->chunk(1000)->each(function ($item) {
                        try {
                            $insertData = $item->toArray();
                            foreach ($insertData as &$datum) {
                                $datum['id'] = SnowFlake::nextIdCache();
                            }
                            $insertData = array_values($insertData);

                            if ($this->isInCkDb) {
                                DishDetailCHModel::query()->insert($insertData);
                            }

                        } catch (\Exception $exception) {
                            self::sendFs('Clickhouse 写入数据异常');
                        }

                        DishDetailModel::query()->insert($insertData);

                    });
                }
                $loopStepTime = time();
            }
            $stepTime        = time();
            $diff            = $stepTime - $systemStartTime;
            $systemStartTime = time();
            $this->info(date("Y-m-d", $date['startTime']) . '的 外卖 数据已经入库至观远, 耗时:' . $diff . "秒");
        }

        $diffTime = time() - $systemStartTimeConst;
        $content  = date('Y-m-d H:i:s',
                $startTimeAt) . ' 至 ' . date('Y-m-d H:i:s',
                $endTimeAt) . ' 外卖数据已经入库至观远,, 耗时' . $diffTime . '秒';

        SendFs::newRobot(SendFs::ROBOT_GUANYUAN)->setTitleContent('夸父-外卖数据 ' . date('Y-m-d H:i:s', time()),
            $content)
              ->send();
    }

    private function getAllCategory()
    {
        $redis = Redis::connection('guanyuan');

        $keyName = 'guanyuan:getAllCategory';
        $data    = $redis->get($keyName);

        if (!$data) {
            // 过期时间 当天的零点
            $expireTime   = strtotime(date('Ymd', strtotime('+1 day'))) - time() + 100;
            $categoryList = CategoryModel::query()->select(['id', 'pid', 'name'])->get()->keyBy('id')->toArray();
            $data         = json_encode($categoryList);
            $redis->setex($keyName, $expireTime, $data);
        }

        return json_decode($data, 1);
    }


    private function getCategoryName($id)
    {
        $list = $this->getAllCategory();
        if (key_exists($id, $list)) {
            return $list[$id]['name'];
        } else {
            return '';
        }
    }

    private function switchCategoryName($sourceType)
    {
        switch ($sourceType) {
            case 3:
                return '美团外卖';
            case 4:
                return '饿了么外卖';
            default:
                return '';
        }
    }


    private function getSourceName($sourceType)
    {
        switch ($sourceType) {
            case 3:
                return '美团';
            case 4:
                return '饿了么';
            default:
                return '';
        }
    }


    private function getDishDetail()
    {
        $dish = file_get_contents(__DIR__ . "/../File/dish.txt");
        $list = explode("\n", $dish);

        $result = [];
        foreach ($list as $one) {
            $tmp             = explode("\t", $one);
            $result[$tmp[1]] = [
                'spuId'         => $tmp[0],
                'spuName'       => $tmp[1],
                'firstCateName' => $tmp[2]
            ];
        }

        return $result;
    }

    private static function sendFs($content, $fsUid = [])
    {
        if (!empty($content)) {
            SendFs::newRobot(SendFs::ROBOT_GUANYUAN)
                  ->setTitleContent('[外卖] ' . date('Y-m-d H:i:s', time()), $content)
                  ->setAtUids($fsUid)
                  ->send();
        }
    }

}
